class_name DragAndDrop
extends Node

# ===============================================

signal drag_started()
signal drag_canceled()
signal dropped(starting_position: Vector2)

# ===============================================

@export var enabled: bool = true
@export var target: Area2D

# ===============================================

var starting_position: Vector2            # 取消释放时返回原位
var offset: Vector2 = Vector2.ZERO        # 记录物体坐标与鼠标坐标间的偏移
var dragging: bool = false

# ===============================================

func __start_dragging() -> void:
	dragging = true
	starting_position = target.global_position
	target.add_to_group("dragging")
	# 确保拖拽物体渲染在最上层
	target.z_index = Arena.MAX_Z_INDEX
	offset = target.global_position - target.get_global_mouse_position()
	drag_started.emit()


func __end_dragging() -> void:
	dragging = false
	target.remove_from_group("dragging")
	target.z_index = 0


func __cancel_dragging() -> void:
	__end_dragging()
	drag_canceled.emit(starting_position)


func __drop() -> void:
	__end_dragging()
	dropped.emit(starting_position)


func __on_target_input_event(_viewport: Node, event: InputEvent) -> void:
	if not enabled:
		return
	# 两个碰撞框重叠，只选取其中一个
	var dragging_object: Node = get_tree().get_first_node_in_group("dragging")
	if dragging or dragging_object:
		return
	if event.is_action_pressed("select"):
		__start_dragging()

# ===============================================

func _ready() -> void:
	assert(target, "No target set for DragAndDrop Component!")
	target.input_event.connect(__on_target_input_event.unbind(1))


func _process(_delta: float) -> void:
	if dragging and target:
		target.global_position = target.get_global_mouse_position() + offset


func _input(event: InputEvent) -> void:
	if dragging and event.is_action_pressed("cancel_drag"):
		__cancel_dragging()
	elif dragging and event.is_action_released("select"):
		__drop()
